package com.treasure.mall.biz.service.core.product.impl;

import com.treasure.mall.biz.base.AbstractSearchableCrudService;
import com.treasure.mall.biz.base.SpecificationAndSort;
import com.treasure.mall.biz.dto.BaseSaveDTO;
import com.treasure.mall.biz.dto.BaseSearchDTO;
import com.treasure.mall.biz.dto.condition.SpecialAreaCondition;
import com.treasure.mall.biz.entity.product.*;
import com.treasure.mall.biz.repository.product.SpecialAreaProductRepository;
import com.treasure.mall.biz.repository.product.SpecialAreaRepository;
import com.treasure.mall.biz.service.core.product.SpecialAreaService;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.base.ResultCodeEnum;
import com.treasure.mall.zbq.common.exception.ApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/6/22
 */
@Service
public class SpecialAreaServiceImpl extends AbstractSearchableCrudService<SpecialAreaProductPO, Long> implements SpecialAreaService {
    @Autowired
    private SpecialAreaRepository areaRepository;

    private SpecialAreaProductRepository areaProductRepository;

    @Autowired
    protected SpecialAreaServiceImpl(SpecialAreaProductRepository repository) {
        super(repository);
        this.areaProductRepository = repository;
    }

    @Override
    protected SpecificationAndSort<SpecialAreaProductPO> specificationAndSort(BaseSearchDTO searchDTO) {
        SpecialAreaCondition condition = (SpecialAreaCondition) searchDTO;

        Specification<SpecialAreaProductPO> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (!StringUtils.isEmpty(condition.getAreaId())) {
                predicates.add(cb.equal(root.get(SpecialAreaProductPO_.areaId), condition.getAreaId()));
            }
            if (!StringUtils.isEmpty(condition.getProductKey())) {
                predicates.add(cb.like(root.get(SpecialAreaProductPO_.productPO).get(ProductPO_.productName), likeAll(condition.getProductKey())));
            }
            if (condition.getStatusCode() != null) {
                predicates.add(cb.equal(root.get(SpecialAreaProductPO_.productPO).get(ProductPO_.statusCode), condition.getStatusCode()));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "orderWeight");

        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public SpecialAreaPO addArea(String areaId, String title, String desc) {
        SpecialAreaPO specialAreaPO = new SpecialAreaPO();
        specialAreaPO.setId(areaId);

        specialAreaPO.setTitle(title);
        specialAreaPO.setDesc(desc);

        return areaRepository.save(specialAreaPO);
    }

    @Override
    public SpecialAreaPO editArea(String areaId, String title, String desc) {
        long count = areaRepository.count();
        SpecialAreaPO specialAreaPO;
        if (StringUtils.isEmpty(areaId)) {
            areaId = String.valueOf((1001 + count));
            specialAreaPO = new SpecialAreaPO();
            specialAreaPO.setId(areaId);
            specialAreaPO.setCreateTime(LocalDateTime.now());
            specialAreaPO.setUpdateTime(LocalDateTime.now());
        } else {
            specialAreaPO = findAreaById(areaId);
        }
        specialAreaPO.setTitle(title);
        specialAreaPO.setDesc(desc);

        return areaRepository.save(specialAreaPO);
    }

    @Override
    @Transactional
    public void addProduct(Long productId, String... areaId) {
        for (String s : areaId) {
            if (areaProductRepository.existsByAreaIdAndProductPO_ProductId(s, productId)) {
                SpecialAreaPO specialAreaPO = findAreaById(s);
                throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "【" + specialAreaPO.getTitle() + "】商品已经存在"));
            }
            SpecialAreaProductPO po = new SpecialAreaProductPO();
            po.setAreaId(s);
            po.setProductPO(new ProductPO(productId));

            save(po);
        }
    }

    @Override
    public void removeProduct(Long id) {
        delete(id);
    }

    @Override
    public List<SpecialAreaPO> areaList() {
        return areaRepository.findAll();
    }

    @Override
    public SpecialAreaPO findAreaById(String id) {
        return areaRepository.findById(id).orElse(null);
    }

    @Override
    public List<SpecialAreaPO> findAreaAll() {
        return areaRepository.findAll();
    }

    @Override
    public SpecialAreaProductPO save(BaseSaveDTO saveDTO) {
        return null;
    }
}
